/*
 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
 */
#include <devices/led_rgb.h>

#include "app_main.h"
#include "app_pwm.h"

#define TAG "app_led"

#define DEVICE_LED_NAME "ledrgb"
#if !defined(LED0_PIN) || !defined(LED0_PIN)
#define LED_ENABLED 0
#else
#define LED_ENABLED 1
#endif

#if LED_ENABLED
static led_pin_config_t led0_config = {LED0_PIN, LED_PIN_NOT_SET, LED_PIN_NOT_SET, LED_FLIP_FLAG};
static led_pin_config_t led1_config = {LED1_PIN, LED_PIN_NOT_SET, LED_PIN_NOT_SET, LED_FLIP_FLAG};

static aos_dev_t *led_dev_0    = NULL;
static aos_dev_t *led_dev_1    = NULL;
static int        g_app_led_en = 1;
static uint8_t g_last_net_led_state = LED_TURN_OFF;

void app_set_led_enabled(int en)
{
    g_app_led_en = en;
}

void app_set_led_state(int state)
{
    if (g_app_led_en == 0) {
        if (led_dev_0) {
            led_close(led_dev_0);
            led_dev_0 = NULL;
        }
        if (led_dev_1) {
            led_close(led_dev_1);
            led_dev_1 = NULL;
        }
        return;
    }

    if (led_dev_0 == NULL) {
        led_rgb_register(&led0_config, 0);

        if (led_dev_0 == NULL) {
            led_dev_0 = led_open_id(DEVICE_LED_NAME, 0);
        }

        if (led_dev_0 == NULL) {
            LOGE(TAG, "led_dev_0 open err!");
            return;
        }
    }

    if (led_dev_1 == NULL) {
        led_rgb_register(&led1_config, 1);

        if (led_dev_1 == NULL) {
            led_dev_1 = led_open_id(DEVICE_LED_NAME, 1);
        }

        if (led_dev_1 == NULL) {
            LOGE(TAG, "led_dev_1 open err!");
            return;
        }
    }

    switch (state) {
        case LED_LOADING:
            led_control(led_dev_0, COLOR_RED, 0, 0);
            break;
        case LED_NET_DOWN:
            led_control(led_dev_1, COLOR_BLACK, 0, 0);
            break;
        case LED_NET_READY:
            led_control(led_dev_1, COLOR_RED, 0, 0);
            break;
        case LED_PLAYING:
            led_control(led_dev_0, COLOR_RED, 50, 1000);
            break;
        case LED_NET_CONFIG:
            led_control(led_dev_1, COLOR_RED, 50, 1000);
            break;
        case LED_TALKING:
            led_control(led_dev_0, COLOR_RED, 0, 0);
            break;
        case LED_IDLE:
            led_control(led_dev_0, COLOR_BLACK, 0, 0);
            break;
        case LED_LPM:
            g_last_net_led_state = LED_LPM;
            led_control(led_dev_0, COLOR_BLACK, 0, 0);
            led_control(led_dev_1, COLOR_BLACK, 0, 0);
            break;
        default:
            led_control(led_dev_0, COLOR_BLACK, 0, 0);
            led_control(led_dev_1, COLOR_BLACK, 0, 0);
            break;
    }

    /* LED lights are working all the time,no need to close.*/
    //led_close(led_dev);
}

static void app_status_event_cb(uint32_t event_id, const void *param, void *context)
{
    aui_player_state_t player_state = AUI_PLAYER_UNKNOWN;
    int mic_busy_state = 0;

    if (event_id == EVENT_UPDATE_STATUS) {
        //LOGD(TAG, ">>>  EVENT_UPDATE_STATUS");

        //网络状态
        if (wifi_is_pairing()) {
            app_set_led_state(LED_NET_CONFIG);
            g_last_net_led_state = LED_NET_CONFIG;
        } else if (wifi_internet_is_connected()) {
            if (g_last_net_led_state != LED_NET_READY) {
                app_set_led_state(LED_NET_READY);
                g_last_net_led_state = LED_NET_READY;
            }
        } else {
            app_set_led_state(LED_NET_DOWN);
            g_last_net_led_state = LED_NET_DOWN;
        }

        player_state = aui_player_get_state(MEDIA_MUSIC);
        mic_busy_state = app_mic_get_busy();

        if (mic_busy_state == 1) {
            app_set_led_state(LED_TALKING);
        } else {
            if (player_state == AUI_PLAYER_PLAYING)
                app_set_led_state(LED_PLAYING);
            else
                app_set_led_state(LED_IDLE);
        }
    }
}

void app_status_init()
{
    /* 事件订阅 */
    event_subscribe(EVENT_UPDATE_STATUS, app_status_event_cb, NULL);
    app_set_led_state(LED_LOADING);
}

void app_status_update(void)
{
    //event_publish(EVENT_UPDATE_STATUS, NULL);
    event_publish_delay(EVENT_UPDATE_STATUS, NULL, 50);
}
#else
void app_set_led_enabled(int en)
{
    ;
}
void app_status_init()
{
    ;
}
void app_set_led_state(int state)
{
    ;
}
void app_status_update(void)
{
    ;
}
#endif

/*****************
 * PWM LED
 *****************/
#if (defined APP_PWM_EN) && APP_PWM_EN
#define PWM_PERIOD 100
typedef struct pwm_led {
    uint8_t status;     /* 0 - stop, 1 - start */
    int32_t brightness; /* 10 - 100 */
    uint32_t pwm_idx;
    pin_name_e pin;
    pin_func_e pin_func;
    uint8_t channel;
} pwm_led_t;
static pwm_led_t g_pwm_led_ctx = {0, 60, PWM0_IDX, PWM0_PIN, PW0_PIN_FUNC, PWM0_CH};

static int app_pwm_led_set_config(int brightness)
{
    int ret = 0;
    int pwm_low_flag = 1;  /* 低电平亮 */
    ret = aos_kv_getint("pwm_low", &pwm_low_flag);
    LOGD(TAG, "pwm_low [%d]", pwm_low_flag);

    if(0 == pwm_low_flag) {
        ret = app_pwm_config(g_pwm_led_ctx.channel, PWM_PERIOD, brightness);
    } else {
        ret = app_pwm_config(g_pwm_led_ctx.channel, PWM_PERIOD, PWM_PERIOD - brightness);
    }
    if (ret != 0) {
        LOGE(TAG, "PWM config failed, channel %d", g_pwm_led_ctx.channel);
    }

    return ret;
}

static int app_pwm_led_set_stop()
{
    LOGD(TAG, "PWM led off.");
    return app_pwm_led_set_config(0);
}

static int app_pwm_led_set_normal()
{
    LOGD(TAG, "PWM led set to brightness %d", g_pwm_led_ctx.brightness);
    int brightness = g_pwm_led_ctx.brightness;
    if (brightness == PWM_LED_LIGHT_MAX) {
        brightness = 99; // Max 99.
    }

    return app_pwm_led_set_config(brightness);
}

int8_t app_pwm_led_init()
{
    int8_t ret = 0;

    int brightness;
    if (aos_kv_getint("led_brightness", &brightness) == 0) {
        g_pwm_led_ctx.brightness = brightness;
    }

    ret = app_pwm_init(g_pwm_led_ctx.pwm_idx, g_pwm_led_ctx.pin, g_pwm_led_ctx.pin_func, g_pwm_led_ctx.channel);
    if (ret != 0) {
        LOGE(TAG, "PWM Init failed, pin %d channel %d", g_pwm_led_ctx.pin, g_pwm_led_ctx.channel);
    }

    app_pwm_led_set_stop();

    mdelay(20);
    ret = app_pwm_start(g_pwm_led_ctx.channel);
    if (ret != 0) {
        LOGE(TAG, "PWM start failed, channel %d", g_pwm_led_ctx.channel);
    }

    g_pwm_led_ctx.status = 0;

    return ret;
}

int8_t app_pwm_led_control(const uint8_t flag)
{
    /* flag: 0 - stop, 1 -start */
    int8_t ret = 0;
    if (0 == flag) {
        if (0 == g_pwm_led_ctx.status) {
            /* already stopped */
            return ret;
        }

        ret = app_pwm_led_set_stop();
        if (0 == ret) {
            g_pwm_led_ctx.status = 0;
#if defined(CONFIG_SMARTLIVING_DEMO) && CONFIG_SMARTLIVING_DEMO
            user_post_property();
#endif
        }
    } else if (1 == flag) {
        LOGD(TAG, "PWM led on.");
        ret = app_pwm_led_set_normal();
        if (0 == ret) {
            g_pwm_led_ctx.status = 1;
#if defined(CONFIG_SMARTLIVING_DEMO) && CONFIG_SMARTLIVING_DEMO
            user_post_property();
#endif
        }
    } else {
        LOGE(TAG, "flag  %d is incorrect!", flag);
        ret = -1;
    }

    return ret;
}

int8_t app_pwm_led_set_brightness(int32_t brightness)
{
    if (brightness < PWM_LED_LIGHT_MIN) {
        brightness = PWM_LED_LIGHT_MIN;
    } else if (brightness > PWM_LED_LIGHT_MAX) {
        brightness = PWM_LED_LIGHT_MAX;
    }

    if (g_pwm_led_ctx.brightness != brightness) {
        if (aos_kv_setint("led_brightness", brightness) != 0) {
            LOGE(TAG, "set led_brightness failed");
        }
    }

    g_pwm_led_ctx.brightness = brightness;

    return app_pwm_led_control(1);
}

int8_t app_pwm_led_get_brightness()
{
    return g_pwm_led_ctx.brightness;
}

int8_t app_pwm_led_get_status()
{
    return g_pwm_led_ctx.status;
}
#endif //APP_PWM_EN
